package com.mspbots.ticketai.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.mspbots.api.client.CoreClient;
import com.mspbots.api.client.WiseClient;
import com.mspbots.ticketai.GradeRuleInterceptorRegistration;
import com.mspbots.ticketai.GradeRuleInterceptorRegistry;
import com.mspbots.ticketai.graderule.GradeRuleInterceptor;
import com.mspbots.ticketai.model.Ticket;
import com.mspbots.ticketai.model.TicketOnly;
import com.mspbots.ticketai.model.TicketRule;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.stream.Collectors;

/**
 * com.mspbots.ticketai.service.BaseService
 *
 * @author Alex bob(https://github.com/vnobo)
 * @date Created by 2019/11/12
 */
@Slf4j
public abstract class BaseService {

    private static String CUSTOM_RULE_NAME = "CUSTOM_GRADE_POINT_RULE";
    protected ObjectMapper objectMapper;
    protected WiseClient wiseClient;
    protected CoreClient coreClient;
    private GradeRuleInterceptorRegistry ruleInterceptorRegistry;

    protected Mono<TicketOnly> graded(List<TicketRule> rules, Ticket ticket) {
        return Mono.just(ticket).flatMap(t -> {
            var boardTicketRules = rules.stream().filter(rule -> rule.getBoard().equals(ticket.getBoardId()))
                    .collect(Collectors.toList());
            List<GradeRuleInterceptor> gradeRuleInterceptors = this.ruleInterceptorRegistry.getInterceptors(boardTicketRules)
                    .parallelStream()
                    .map(GradeRuleInterceptorRegistration::getInterceptor)
                    .collect(Collectors.toList());
            gradeRuleInterceptors.forEach(gradeRuleInterceptor -> {
                try {
                    gradeRuleInterceptor.process(t);
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            });
            return Mono.just(t);
        }).flatMap(t -> {
            var customTicketRules = rules.stream().filter(rule -> CUSTOM_RULE_NAME.equals(rule.getName()))
                    .collect(Collectors.toList());
            var customRuleInterceptors = this.ruleInterceptorRegistry.getInterceptors(customTicketRules)
                    .parallelStream()
                    .map(GradeRuleInterceptorRegistration::getInterceptor).findFirst();
            if (customRuleInterceptors.isPresent()) {
                try {
                    return customRuleInterceptors.get().syncProcess(t);
                } catch (Exception e) {
                    log.error(e.getMessage());
                }
            }
            return Mono.just(t);
        }).map(tk -> {
            TicketOnly ticketOnly = new TicketOnly();
            BeanUtils.copyProperties(tk, ticketOnly);
            return ticketOnly;
        });
    }

    @Autowired
    public void setRuleInterceptorRegistry(GradeRuleInterceptorRegistry ruleInterceptorRegistry) {
        this.ruleInterceptorRegistry = ruleInterceptorRegistry;
    }

    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Autowired
    public void setWiseClient(WiseClient wiseClient) {
        this.wiseClient = wiseClient;
    }

    @Autowired
    public void setCoreClient(CoreClient coreClient) {
        this.coreClient = coreClient;
    }
}
